#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <cassert>
class thread;

class thread
{
    // function<void*(void*)>是类无法直接传递给pthread_create,需要间接传递
    typedef std::function<void *(void *)> func_t;
    // 使用结构体context保存线程指针,便于cpp/c混编
    struct context
    {
        context()
            : _this(nullptr), _arg(nullptr) {}

        ~context() {}

    public:
        thread *_this;
        void *_arg;
    };

public:
    thread(func_t func = nullptr, void *arg = nullptr, int num = 0)
        : _func(func), _arg(arg), _tid(0)
    {
        char buffer[255];
        snprintf(buffer, sizeof buffer, "thread-%d", num);
        _name = buffer;
    }

    // 作为代理函数间接解决传参问题
    static void *broker_func(void *arg)
    {
        context *ct = static_cast<context *>(arg);
        void *ret = ct->_this->run(ct->_arg);
        // 执行任务结束回收ct资源
        delete ct;
        return ret;
    }

    int create()
    {
        context *ct = new context();
        ct->_this = this;
        ct->_arg = _arg;
        int ret = pthread_create(&_tid, nullptr, broker_func, ct);
        // delete ct; 不能在创建后立即销毁,防止线程调度后线程运行代理函数中途ct失效发生段错误segament fault,应在线程任务执行结束后销毁ct
        return ret;
    }

    // 保护分配给线程任务,只提供使用接口
    void *run(void *arg)
    {
        return _func(arg);
    }

    void push(func_t task, void* args)
    {
        _func = task;
        _arg = args;
    }

    int detach()
    {
        int ret = pthread_detach(_tid);
        assert(ret == 0);
        return ret;
    }

    int join()
    {
        int ret = pthread_join(_tid, nullptr);
        assert(ret == 0);
        return ret;
    }

    ~thread() {}

private:
    std::string _name;
    pthread_t _tid;
    func_t _func;
    void *_arg;
};
